﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using 命令处理机;

namespace 命令解释器
{
    /// <summary>
    /// 命令执行方法
    /// </summary>
    /// <param name="args">参数</param>
    public delegate void CommandHandleMethod(CommandInfo args);

    /// <summary>
    /// 命令解释器
    /// </summary>
    public class CommandInterpreter
    {
        /// <summary>
        /// 命令处理方法
        /// </summary>
        private Dictionary<string, CommandHandleMethod> HandlerMethods;

        public CommandInterpreter()
        {
            HandlerMethods = new Dictionary<string, CommandHandleMethod>();
        }

        /// <summary>
        /// 注册处理机
        /// </summary>
        /// <param name="cmd">申请的命令</param>
        /// <param name="method">处理方法</param>
        public void Register(string cmd, CommandHandleMethod method)
        {
            HandlerMethods.Add(cmd.ToUpper(), method);
        }

        /// <summary>
        /// 卸载处理机
        /// </summary>
        /// <param name="cmd">目标命令</param>
        public void deregister(string cmd)
        {
            HandlerMethods.Remove(cmd.ToUpper());
        }

        /// <summary>
        /// 单行命令解释
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>命令信息</returns>
        public CommandInfo SingleLineInterpret(string str)
        {
            string[] tmp = str.Split(new char[] { ' ' });
            string cmd = tmp[0];

            List<string> args = new List<string>(tmp.Length);
            for (int i = 1; i < tmp.Length; i++)
            {
                if (tmp[i].Length > 0)
                {
                    args.Add(tmp[i]);
                }
            }
            return new CommandInfo(cmd, args.ToArray());
        }

        /// <summary>
        /// 多行命令解释
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>命令信息</returns>
        public CommandInfo MultiLineInterpret(string str)
        {
            int i = str.IndexOf(CommandInfo.NewLine);
            if (i == -1)
            {
                string cmd = str.Substring(0, str.Length);
                return new CommandInfo(cmd, "");
            }
            else
            {
                string cmd = str.Substring(0, i).Trim();
                i += CommandInfo.NewLine.Length;
                string arg = str.Substring(i);
                return new CommandInfo(cmd, arg);
            }
        }
        
        /// <summary>
        /// 解释命令
        /// </summary>
        /// <param name="str">目标字符串</param>
        public void Interpret(string str)
        {
            Stream s = new MemoryStream(ASCIIEncoding.Default.GetBytes(str));
            StreamReader reader = new StreamReader(s, ASCIIEncoding.Default);
            bool inMultiCMD = false;
            string line;
            List<string> buf = new List<string>();

            while ((line = reader.ReadLine()) != null)
            {
                if (inMultiCMD)
                {
                    if (line.TrimStart().StartsWith("###"))
                    {
                        inMultiCMD = false;
                        CommandInfo info = MultiLineInterpret(string.Join(CommandInfo.NewLine, buf.ToArray()));
                        buf.Clear();
                        Execute(info);
                    }
                    else
                    {
                        buf.Add(line);
                    }
                }
                else
                {
                    line = line.Trim();
                    if (line.StartsWith("#"))
                    {
                        inMultiCMD = true;
                        buf.Add(line);
                    }
                    else
                    {
                        CommandInfo info = SingleLineInterpret(line);
                        Execute(info);
                    }
                }
            }
        }

        /// <summary>
        /// 解释带扩展命令
        /// </summary>
        /// <param name="str">目标字符串</param>
        /// <param name="attach">扩展</param>
        public void Interpret(string str, Dictionary<string, object> attach)
        {
            Stream s = new MemoryStream(ASCIIEncoding.Default.GetBytes(str));
            StreamReader reader = new StreamReader(s, ASCIIEncoding.Default);
            bool inMultiCMD = false;
            string line;
            List<string> buf = new List<string>();
            attach.Add("Interpreter", this);

            while ((line = reader.ReadLine()) != null)
            {
                if (inMultiCMD)
                {
                    if (line.TrimStart().StartsWith("###"))
                    {
                        inMultiCMD = false;
                        CommandInfo info = MultiLineInterpret(string.Join(CommandInfo.NewLine, buf.ToArray()));
                        buf.Clear();
                        info.Attach = attach;
                        Execute(info);
                    }
                    else
                    {
                        buf.Add(line);
                    }
                }
                else
                {
                    line = line.Trim();
                    if (line.StartsWith("#"))
                    {
                        inMultiCMD = true;
                        buf.Add(line);
                    }
                    else
                    {
                        CommandInfo info = SingleLineInterpret(line);
                        info.Attach = attach;
                        Execute(info);
                    }
                }
            }
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="info">命令参数</param>
        /// <returns>能否执行</returns>
        public bool Execute(CommandInfo info)
        {
            try
            {
                CommandHandleMethod method = HandlerMethods[info.Command];
                method(info);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
